home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / lib / From MoreFiles / IterateDirectory.c < prev    next >
Text File  |  2001-07-23  |  6KB  |  190 lines

  1. /*
  2. **    IterateDirectory: File Manager directory iterator routines.
  3. **
  4. **    by Jim Luther
  5. **
  6. **    File:        IterateDirectory.c
  7. **
  8. **    Copyright ゥ 1995-1998 Jim Luther and Apple Computer, Inc.
  9. **    All rights reserved.
  10. **
  11. **    You may incorporate this sample code into your applications without
  12. **    restriction, though the sample code has been provided "AS IS" and the
  13. **    responsibility for its operation is 100% yours.
  14. **
  15. **    IterateDirectory is designed to drop into the MoreFiles sample code
  16. **    library I wrote while in Apple Developer Technical Support
  17. */
  18.  
  19. #include <Types.h>
  20. #include <Errors.h>
  21. #include <Files.h>
  22.  
  23. #define    __COMPILINGMOREFILES
  24.  
  25. #include "MoreFilesExtras.h"
  26. #include "IterateDirectory.h"
  27.  
  28. /*
  29. **    Type definitions
  30. */
  31.  
  32. /* The IterateGlobals structure is used to minimize the amount of
  33. ** stack space used when recursively calling IterateDirectoryLevel
  34. ** and to hold global information that might be needed at any time.
  35. */
  36. #if PRAGMA_ALIGN_SUPPORTED
  37. #pragma options align=mac68k
  38. #endif
  39. struct IterateGlobals
  40. {
  41.     IterateFilterProcPtr    iterateFilter;    /* pointer to IterateFilterProc */
  42.     CInfoPBRec                cPB;            /* the parameter block used for PBGetCatInfo calls */
  43.     Str63                    itemName;        /* the name of the current item */
  44.     OSErr                    result;            /* temporary holder of results - saves 2 bytes of stack each level */
  45.     Boolean                    quitFlag;        /* set to true if filter wants to kill interation */
  46.     unsigned short            maxLevels;        /* Maximum levels to iterate through */
  47.     unsigned short            currentLevel;    /* The current level IterateLevel is on */
  48.     void                    *yourDataPtr;    /* A pointer to caller data the filter may need to access */
  49. };
  50. #if PRAGMA_ALIGN_SUPPORTED
  51. #pragma options align=reset
  52. #endif
  53.  
  54. typedef struct IterateGlobals IterateGlobals;
  55. typedef IterateGlobals *IterateGlobalsPtr;
  56.  
  57. /*****************************************************************************/
  58.  
  59. /*    Static Prototype */
  60.  
  61. static    void    IterateDirectoryLevel(long dirID,
  62.                                       IterateGlobals *theGlobals);
  63.  
  64. /*****************************************************************************/
  65.  
  66. /*
  67. **    Functions
  68. */
  69.  
  70. static    void    IterateDirectoryLevel(long dirID,
  71.                                       IterateGlobals *theGlobals)
  72. {
  73.     if ( (theGlobals->maxLevels == 0) ||                        /* if maxLevels is zero, we aren't checking levels */
  74.          (theGlobals->currentLevel < theGlobals->maxLevels) )    /* if currentLevel < maxLevels, look at this level */
  75.     {
  76.         short index = 1;
  77.         
  78.         ++theGlobals->currentLevel;    /* go to next level */
  79.         
  80.         do
  81.         {    /* Isn't C great... What I'd give for a "WITH theGlobals DO" about now... */
  82.         
  83.             /* Get next source item at the current directory level */
  84.             
  85.             theGlobals->cPB.dirInfo.ioFDirIndex = index;
  86.             theGlobals->cPB.dirInfo.ioDrDirID = dirID;
  87.             theGlobals->result = PBGetCatInfoSync((CInfoPBPtr)&theGlobals->cPB);        
  88.     
  89.             if ( theGlobals->result == noErr )
  90.             {
  91.                 /* Call the IterateFilterProc */
  92.                 CallIterateFilterProc(theGlobals->iterateFilter, &theGlobals->cPB, &theGlobals->quitFlag, theGlobals->yourDataPtr);
  93.                 
  94.                 /* Is it a directory? */
  95.                 if ( (theGlobals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
  96.                 {
  97.                     /* We have a directory */
  98.                     if ( !theGlobals->quitFlag )
  99.                     {
  100.                         /* Dive again if the IterateFilterProc didn't say "quit" */
  101.                         IterateDirectoryLevel(theGlobals->cPB.dirInfo.ioDrDirID, theGlobals);
  102.                     }
  103.                 }
  104.             }
  105.             
  106.             ++index; /* prepare to get next item */
  107.         } while ( (theGlobals->result == noErr) && (!theGlobals->quitFlag) ); /* time to fall back a level? */
  108.         
  109.         if ( (theGlobals->result == fnfErr) ||    /* fnfErr is OK - it only means we hit the end of this level */
  110.              (theGlobals->result == afpAccessDenied) ) /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
  111.         {
  112.             theGlobals->result = noErr;
  113.         }
  114.             
  115.         --theGlobals->currentLevel;    /* return to previous level as we leave */
  116.     }
  117. }
  118.  
  119. /*****************************************************************************/
  120.  
  121. pascal    OSErr    IterateDirectory(short vRefNum,
  122.                                  long dirID,
  123.                                  ConstStr255Param name,
  124.                                  unsigned short maxLevels,
  125.                                  IterateFilterProcPtr iterateFilter,
  126.                                  void *yourDataPtr)
  127. {
  128.     IterateGlobals    theGlobals;
  129.     OSErr            result;
  130.     long            theDirID;
  131.     short            theVRefNum;
  132.     Boolean            isDirectory;
  133.     
  134.     /* Make sure there is a IterateFilter */
  135.     if ( iterateFilter != NULL )
  136.     {
  137.         /* Get the real directory ID and make sure it is a directory */
  138.         result = GetDirectoryID(vRefNum, dirID, name, &theDirID, &isDirectory);
  139.         if ( result == noErr )
  140.         {
  141.             if ( isDirectory == true )
  142.             {
  143.                 /* Get the real vRefNum */
  144.                 result = DetermineVRefNum(name, vRefNum, &theVRefNum);
  145.                 if ( result == noErr )
  146.                 {
  147.                     /* Set up the globals we need to access from the recursive routine. */
  148.                     theGlobals.iterateFilter = iterateFilter;
  149.                     theGlobals.cPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
  150.                     theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
  151.                     theGlobals.itemName[0] = 0;
  152.                     theGlobals.result = noErr;
  153.                     theGlobals.quitFlag = false;
  154.                     theGlobals.maxLevels = maxLevels;
  155.                     theGlobals.currentLevel = 0;    /* start at level 0 */
  156.                     theGlobals.yourDataPtr = yourDataPtr;
  157.                 
  158.                     /* Here we go into recursion land... */
  159.                     IterateDirectoryLevel(theDirID, &theGlobals);
  160.                     
  161.                     result = theGlobals.result;    /* set the result */
  162.                 }
  163.             }
  164.             else
  165.             {
  166.                 result = dirNFErr;    /* a file was passed instead of a directory */
  167.             }
  168.         }
  169.     }
  170.     else
  171.     {
  172.         result = paramErr;    /* iterateFilter was NULL */
  173.     }
  174.     
  175.     return ( result );
  176. }
  177.  
  178. /*****************************************************************************/
  179.  
  180. pascal    OSErr    FSpIterateDirectory(const FSSpec *spec,
  181.                                     unsigned short maxLevels,
  182.                                     IterateFilterProcPtr iterateFilter,
  183.                                     void *yourDataPtr)
  184. {
  185.     return ( IterateDirectory(spec->vRefNum, spec->parID, spec->name,
  186.                         maxLevels, iterateFilter, yourDataPtr) );
  187. }
  188.  
  189. /*****************************************************************************/
  190.